/*******************************************************************
 * Copyright (c) 2013 珠海比特讯科技有限公司. All rights reserved.
 * （1）软件的版权将受到法律保护，不允许非经授权的使用；
 * （2）未经版权所有人授权，任何人不得修改、复制和传播软件源代码、图片及其它资源等；
 * （3）未经版权所有人授权，不允许对软件进行修改；
 * （4）未经版权所有人授权，不允许在该软件的基础上开发新的软件；
 * （5）珠海比特讯科技有限公司拥有最终解释权
 *******************************************************************/
package youxiao.bytezon.utils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import org.springframework.beans.BeanUtils;
import org.springframework.util.ClassUtils;

public class BeanUtil {
	
	// 不拷贝关系，否则会一直遍历关系及关系表
	public static void copyTableProps(Object tableObject, Object viewObject) {
		// tableObject 往往是代理对象（被代理的对象类型属性是动态生成的），一般是用到时，属性才会加载进来。如果是lazy模式，往往刚开始时就是一个空属性的对象。后面被调用时，tableObject.getClass().getDeclaredFields()才能取到
		// 这里使用 ClassUtils.getUserClass 取出 tableObject 原本被代理的对象类型
		Class<?> clazz = ClassUtils.getUserClass(tableObject.getClass());
		
		Set<String> ignoreProperties = new HashSet<String>();
		for(Field field : clazz.getDeclaredFields()){
		  if(isAssociationsField(field)) {
		  		ignoreProperties.add(field.getName());
		  }
		}
		BeanUtils.copyProperties(tableObject, viewObject, ignoreProperties.toArray(new String[ignoreProperties.size()]));
	}
	
	public static void copyTableProps(Object tableObject, Object viewObject, String... ignoreProps) {
		Set<String> ignoreProperties = new HashSet<String>(Arrays.asList(ignoreProps));
		for(Field field : tableObject.getClass().getDeclaredFields()){
		  if(isAssociationsField(field)) {
		  	ignoreProperties.add(field.getName());
		  }
		}
		
		BeanUtils.copyProperties(tableObject, viewObject, ignoreProperties.toArray(new String[ignoreProperties.size()]));
	}
	
	private static boolean isAssociationsField(Field field) {
		Annotation[] annotations = field.getDeclaredAnnotations();
		for (Annotation annotation : annotations) {
			Class<? extends Annotation> clazz = annotation.annotationType();
			if (clazz.equals(OneToMany.class) || clazz.equals(ManyToMany.class) || clazz.equals(ManyToOne.class) || clazz.equals(OneToOne.class)) {
				return true;
			}
		}
		
		return false;
	}
	
}
